package com.k8.rpc.result;

import com.k8.rpc.RpcException;

import java.util.Collections;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.*;

public class RpcResult<T> implements Result<T> {
    private Map<String, Object> attachments;
    private volatile T value;
    private volatile Throwable exception;


    @Override
    public T getValue() {
        return this.value;
    }

    @Override
    public void setValue(T value) {
        this.value = value;
    }


    @Override
    public Throwable getException() {
        return this.exception;
    }

    @Override
    public void setException(Throwable t) {
        this.exception = t;
    }

    @Override
    public boolean hasException() {
        if (exception == null) return false;
        return true;
    }

    private void initAttachments(int size) {
        if (attachments == null) attachments = new TreeMap<>();
    }

    private void initAttachments() {
        if (attachments == null) attachments = new TreeMap<>();
    }

    @Override
    public Map<String, String> getAttachments() {
        if (this.attachments == null) return Collections.emptyMap();
        TreeMap<String, String> result = new TreeMap<>();
        attachments.forEach((key, value) -> {
            if (value instanceof String sV) result.put(key, sV);
        });
        return result;
    }

    @Override
    public Map<String, Object> getObjectAttachments() {
        if (this.attachments == null) return Collections.emptyMap();
        return this.attachments;
    }

    @Override
    public void addAttachments(Map<String, String> map) {
        initAttachments(map.size());
        map.forEach((key, value) -> {
            this.attachments.put(key, value);
        });
    }

    @Override
    public void addObjectAttachments(Map<String, Object> map) {
        initAttachments(map.size());
        map.forEach((key, value) -> {
            this.attachments.put(key, value);
        });
    }

    @Override
    public void setAttachments(Map<String, String> map) {
        this.attachments = new TreeMap<>();
        map.forEach((key, value) -> {
            attachments.put(key, value);
        });
    }

    @Override
    public void setObjectAttachments(Map<String, Object> map) {
        this.attachments = map;
    }

    @Override
    public String getAttachment(String key) {
        if (attachments == null) return null;
        return (String) attachments.get(key);
    }

    @Override
    public Object getObjectAttachment(String key) {
        if (attachments == null) return null;
        return attachments.get(key);
    }

    @Override
    public String getAttachment(String key, String defaultValue) {
        if (attachments == null) return defaultValue;
        Object value = attachments.get(key);
        if (!(value instanceof String)) return defaultValue;
        return (String) value;
    }

    @Override
    public Object getObjectAttachment(String key, Object defaultValue) {
        if (attachments == null) return defaultValue;
        Object value = attachments.get(key);
        return value == null ? defaultValue : value;
    }

    @Override
    public void setAttachment(String key, String value) {
        initAttachments();
        this.attachments.put(key, value);
    }

    @Override
    public void setObjectAttachment(String key, Object value) {
        initAttachments();
        this.attachments.put(key, value);
    }
}
